// 整个项目的核心配置信息
// 它会直接影响启动效果

use std::collections::HashMap;

use config::ValueKind;
use config::{Config, ConfigError};
use sea_orm::sea_query::Table;
use serde::Deserialize;
use config::File as ConfigFile;
use config::Value;

lazy_static!{
	static ref t_free_config:FreeConfig = {
		let a = Config::builder()
		.set_default("mysql.config", MySQLConfig::default()).unwrap()
		.add_source(ConfigFile::new("./free_config.toml", config::FileFormat::Toml))
		.build();
		let a = match a {
			Ok(v) => v,
			Err(e) =>{
				match e {
					ConfigError::NotFound(e) => {
						panic!("\n[free_config.toml]未找到配置属性;{}\n",e)
					},
					ConfigError::Foreign(e) => {
						// ... 就这样吧
						// 生成配置文件
						std::fs::copy(
							"src/resource/template/free_config.toml"
							, "./free_config.toml")
							.expect("Copy 配置文件出现错误");
						panic!("未找到配置文件,已经在本地生成")
					}
					e => panic!("\n配置文件[free_config.toml]异常;{}\n",e)
				}
			}
		}; 
		// println!("{:#?}",&a);
		a.try_deserialize().expect("[free_config.toml]配置文件存在问题,序列化错误")
	};
	pub static ref FREE_CONFIG:&'static FreeConfig = {
		&*t_free_config
	};
}

#[derive(Deserialize,Debug)]
pub struct FreeConfig{
	pub app:App,
	pub log:Log,
	pub mysql:MySQL,
	pub qq_email:QQEmail,
	pub path:Path
}
#[derive(Deserialize,Debug)]
pub struct App {
	pub port:u16,
	pub address:String,
	pub workers:Option<usize>
}
#[derive(Deserialize,Debug)]
pub struct MySQL {
	pub url:String,
	pub user:String,
	pub password:String,
	pub config:MySQLConfig,
}
#[derive(Deserialize,Debug)]
pub struct MySQLConfig{
	pub sqlx_log:bool,
	pub max_connections:u64,
	pub min_connections:u64,
	pub connect_timeout:u64,
	pub idle_timeout:u64,
	pub max_lifetime:u64
}
impl Default for MySQLConfig {
    fn default() -> Self {
        Self { 
			sqlx_log: true,
			max_connections: 100,
			min_connections: 5, 
			connect_timeout: 8,
			idle_timeout: 8, 
			max_lifetime:8
		}
    }
}
impl From<MySQLConfig> for  Value  {
    fn from(a: MySQLConfig) -> Self {
		let or = String::from("free_config.toml");
		let hs =vec![
			//我尼* ,咋不内置一个u32呢
			//而且,我尼* ,用U64有bug,只能用I64,好像是序列化的问题,艹
			(String::from("sqlx_log"),Value::new(Some(&or),ValueKind::Boolean(a.sqlx_log))),
			(String::from("max_connections"),Value::new(Some(&or),ValueKind::I64(a.max_connections as i64))),
			(String::from("min_connections"),Value::new(Some(&or),ValueKind::I64(a.min_connections as i64))),
			(String::from("connect_timeout"),Value::new(Some(&or),ValueKind::I64(a.connect_timeout as i64))),
			(String::from("idle_timeout"),Value::new(Some(&or),ValueKind::I64(a.idle_timeout as i64))),
			(String::from("max_lifetime"),Value::new(Some(&or),ValueKind::I64(a.max_lifetime as i64))),
			];
		let hs = hs.into_iter().collect();
        Value::new(None
			, ValueKind::Table(hs))
    }
}


#[derive(Deserialize,Debug)]
pub struct QQEmail {
	pub name:Option<String>,
	pub account:String,
	pub code:String,
}

#[derive(Deserialize,Debug)]
pub struct Log {
	pub app_server_Logger_log:bool,
	pub app_server_Logger_format:String
}
#[derive(Deserialize,Debug)]
pub struct Path {
	pub root:String,
	pub cent_piece:String,
	pub tem:String
}